package security.crypto;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import utils.Base64Processing;

public class AssimEncryption {

	public static KeyPair generateKeyPair(){
		try {
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
			keyPairGenerator.initialize(1024);

			return keyPairGenerator.genKeyPair();
		} catch (NoSuchAlgorithmException e) {
			return null;
		}
	}

	public static String signHash(String input, PrivateKey privateKey){
		try {
			byte[] inputBytes = input.getBytes("UTF-8");

			Cipher rsaCipher = Cipher.getInstance("RSA");
			rsaCipher.init(Cipher.ENCRYPT_MODE, privateKey);

			byte[] cipheredBytes = rsaCipher.doFinal(inputBytes);

			return Base64Processing.encodeData(cipheredBytes);
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch (NoSuchAlgorithmException e) {
			return null;
		} catch (NoSuchPaddingException e) {
			return null;
		} catch (InvalidKeyException e) {
			return null;
		} catch (IllegalBlockSizeException e) {
			return null;
		} catch (BadPaddingException e) {
			return null;
		} catch(Exception e){
			return null;
		}
	}

	public static boolean validateSignature(String originalMessage, String signedMessage, PublicKey publicKey){
		try {
			byte[] signedMessageBytes = Base64Processing.decodeData(signedMessage);

			Cipher rsaCipher = Cipher.getInstance("RSA");
			rsaCipher.init(Cipher.DECRYPT_MODE, publicKey);

			byte[] decipheredBytes = rsaCipher.doFinal(signedMessageBytes);

			String designedMessage = new String(decipheredBytes, "UTF-8");

			if(originalMessage.equals(designedMessage))
				return true;
		} catch (UnsupportedEncodingException e) {
			return false;
		} catch (NoSuchAlgorithmException e) {
			return false;
		} catch (NoSuchPaddingException e) {
			return false;
		} catch (InvalidKeyException e) {
			return false;
		} catch (IllegalBlockSizeException e) {
			return false;
		} catch (BadPaddingException e) {
			return false;
		} catch(Exception e){
			return false;
		}

		return false;

	}

	public static String signWebServerMessage(String serializedSignature,
			PrivateKey privateKey) {

		try {
			byte[] signatureBytes = serializedSignature.getBytes("UTF-8");

			Signature signer = Signature.getInstance("SHA1withRSA");
			signer.initSign(privateKey);
			signer.update(signatureBytes);

			return Base64Processing.encodeData(signer.sign());		
		} catch (NoSuchAlgorithmException e) {
			return null;
		} catch (InvalidKeyException e) {
			return null;
		} catch (SignatureException e) {
			return null;
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch(Exception e){
			return null;
		}
	}

	public static boolean validateWebServerSignature(String originalMessage, String cipheredSignature,PublicKey publicKey) {

		try {
			Signature verifySignature = Signature.getInstance("SHA1withRSA");
			verifySignature.initVerify(publicKey);
			verifySignature.update(originalMessage.getBytes("UTF-8"));

			return verifySignature.verify(Base64Processing.decodeData(cipheredSignature));
		} catch (NoSuchAlgorithmException e) {
			return false;
		} catch (InvalidKeyException e) {
			return false;
		} catch (SignatureException e) {
			return false;
		} catch (UnsupportedEncodingException e) {
			return false;
		} catch(Exception e){
			return false;
		}
	}

	public static String cipher(String input, PublicKey publicKey){
		try {
			byte[] inputBytes = input.getBytes("UTF-8");

			Cipher rsaCipher = Cipher.getInstance("RSA");
			rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);

			byte[] cipheredBytes = rsaCipher.doFinal(inputBytes);

			return Base64Processing.encodeData(cipheredBytes);
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch (NoSuchAlgorithmException e) {
			return null;
		} catch (NoSuchPaddingException e) {
			return null;
		} catch (InvalidKeyException e) {
			return null;
		} catch (IllegalBlockSizeException e) {
			return null;
		} catch (BadPaddingException e) {
			return null;
		} catch(Exception e){
			return null;
		}		
	}

	public static String decipher(String input, PrivateKey privateKey){
		try {
			byte[] inputBytes = Base64Processing.decodeData(input);

			Cipher rsaCipher = Cipher.getInstance("RSA");
			rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);

			byte[] decipheredBytes = rsaCipher.doFinal(inputBytes);

			return new String(decipheredBytes, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		} catch (NoSuchAlgorithmException e) {
			return null;
		} catch (NoSuchPaddingException e) {
			return null;
		} catch (InvalidKeyException e) {
			return null;
		} catch (IllegalBlockSizeException e) {
			return null;
		} catch (BadPaddingException e) {
			return null;
		} catch(Exception e){
			return null;
		}
	}

	public static boolean verifyCcSignature(String originalMessage, String signedMessage, Certificate certificate){
		if(originalMessage == null || signedMessage == null){
			System.out.println("The message provided or the signature is null");
			return false;
		}

		try {
			Signature verifySignature = Signature.getInstance("SHA1withRSA");
			verifySignature.initVerify(certificate);
			verifySignature.update(originalMessage.getBytes());

			return verifySignature.verify(Base64Processing.decodeData(signedMessage));

		} catch (NoSuchAlgorithmException e) {
			System.out.println("The signature algorithm used is not available!! \n");
			return false;
		} catch (InvalidKeyException e) {
			System.out.println("The Key Provided is not valid!! \n");
			return false;
		} catch (SignatureException e) {
			System.out.println("The signature has not been verified!! \n");
			return false;
		} catch(Exception e){
			return false;
		}
	}




}
